package com.ruoyi.ghxx.aop;

import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.UUID;

/**
 * 公共字段切面
 * @author cl
 * @date 2020-11-20
 */
@Aspect  // 使用@Aspect注解声明一个切面
@Component
public class SysInitDataAspect {
     /**
     * 这里我们使用注解的形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut("@annotation(com.ruoyi.ghxx.aop.SysInitData)")
    public void logPointCut() {}

    /**
     * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
     * @param point
     * @return
     * @throws Throwable
     */
    @Before("logPointCut()")
    public Object around(JoinPoint point) throws Throwable {
        Object result = point.getArgs();
        try {
            initData(point);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 保存日志
     * @param joinPoint
     */
    private Object initData(JoinPoint joinPoint) throws  Throwable{
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysInitData sysLog = method.getAnnotation(SysInitData.class);
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if(sysLog != null){
            //请求的 类名、方法名
//            String className = joinPoint.getTarget().getClass().getSuperclass().getName();
//            String methodName = signature.getName();
            //请求的参数
            Object[] args = joinPoint.getArgs();
            Object object = args[0];
            if (object != null) {
                Class objectClass = object.getClass().getSuperclass();
                Field[] fs = objectClass.getDeclaredFields();
                for(Field f : fs) {
                    if("createBy".equals(f.getName())){
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try{
                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getCreateBy");
                            Object o=getOrgIdMethod.invoke(object);
                            if(o==null){
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setCreateBy", String.class);
                                setOrgIdMethod.invoke(object, loginUser.getUsername());
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if("createTime".equals(f.getName())){
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try{
                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getCreateTime");
                            Object o=getOrgIdMethod.invoke(object);
                            if(o==null){
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setCreateTime", Date.class);
                                setOrgIdMethod.invoke(object, new Date());
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if("updateTime".equals(f.getName())){
                        /*
                         * 填充字段 orgId 有则取，没有则塞
                         * Method method=null;
                         */
                        try{
                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getUpdateTime");
                            Object o=getOrgIdMethod.invoke(object);
                            Method setOrgIdMethod = objectClass.getDeclaredMethod("setUpdateTime", Date.class);
                            setOrgIdMethod.invoke(object, new Date());
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if ("updateBy".equals(f.getName())){
                        try{
                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getUpdateBy");
                            Object o=getOrgIdMethod.invoke(object);
                            Method setOrgIdMethod = objectClass.getDeclaredMethod("setUpdateBy", String.class);
                            setOrgIdMethod.invoke(object, loginUser.getUsername());
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if("deptIdStrs".equals(f.getName())){
                        try{

                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getDeptIdStrs");
                            Object o=getOrgIdMethod.invoke(object);
                            if(o==null) {
                                String deptIds=","+loginUser.getUser().getDept().getAncestors()+","+loginUser.getUser().getDeptId()+",";
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setDeptIdStrs", String.class);
                                setOrgIdMethod.invoke(object, deptIds);
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if("guid".equals(f.getName())){
                        try{
                            Method getOrgIdMethod=objectClass.getDeclaredMethod("getGuid");
                            Object o=getOrgIdMethod.invoke(object);
                            if(o==null) {
                                Method setOrgIdMethod = objectClass.getDeclaredMethod("setGuid", String.class);
                                setOrgIdMethod.invoke(object,UUID.randomUUID().toString());
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return joinPoint.getArgs();
    }
}
